package com.chenwc.aliyunoss;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONWriter;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectMetadata;
import com.chenwc.common.fileUtils.ReadFile;
import okhttp3.*;
import org.junit.jupiter.api.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.activation.MimetypesFileTypeMap;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author chenwc
 */
public class AliyunOssTest {
    private static final Logger log = LoggerFactory.getLogger(AliyunOssTest.class);

    /**
     * 在测试类执行之前执行的方法 必须用static
     */
    @BeforeAll
    public static void beforeAll() {
        EndpointEnum endpointEnum = EndpointEnum.OSS_CN_GUANGZHOU;
        AliyunOssUtil.getOssClient("",
                "", endpointEnum);
        AliyunOssUtil.getOssClient();
    }

    /**
     * 在每个测试用例后执行的方法 必须用static声明
     */
    @AfterAll
    public static void afterAll() {
        AliyunOssUtil.closeOssClient();
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("listBuckets")
    void listBuckets() {
        JSONArray buckets = AliyunOssUtil.listBuckets();
        log.info("buckets:{}", buckets);
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("isExistBucket")
    void isExistBucket() {
        boolean isExistBucket = AliyunOssUtil.isExistBucket("wxhntmy");
        log.info("isExistBucket:{}", isExistBucket);
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("createBucket")
    void createBucket() {
        AliyunOssUtil.createBucket("wxhntmy");
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("getBucketLocation")
    void getBucketLocation() {
        String bucketLocation = AliyunOssUtil.getBucketLocation("wxhntmy");
        log.info("bucketLocation:{}", bucketLocation);
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("getBucketInfo")
    void getBucketInfo() {
        JSONObject bucketInfo = AliyunOssUtil.getBucketInfo("wxhntmy");
        log.info("bucketInfo:{}", bucketInfo);
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("getBucketStat")
    void getBucketStat() {
        JSONObject bucketStat = AliyunOssUtil.getBucketStat("wxhntmy");
        log.info("bucketStat:{}", bucketStat);
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("getResourceGroupId")
    void getResourceGroupId() {
        String resourceGroupId = AliyunOssUtil.getResourceGroupId("wxhntmy");
        log.info("resourceGroupId:{}", resourceGroupId);
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("setBucketTagging")
    void setBucketTagging() {
        Map<String, String> tagMap = new HashMap<>();
        tagMap.put("tag1", "value1");
        tagMap.put("tag2", "value2");
        AliyunOssUtil.setBucketTagging("wxhntmy", tagMap);
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("deleteBucket")
    void deleteBucket() {
        AliyunOssUtil.deleteBucket("wxhntmy");
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("setBucketResourceGroup")
    void setBucketResourceGroup() {
        AliyunOssUtil.setBucketResourceGroup("wxhntmy", "rg-acfmxwf3xxxxxxxx");
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("uploadObject")
    void uploadObject() {
        File file = new File("D:\\Downloads\\1711893101642.jpg");
        AliyunOssUtil.uploadObject("wxhntmy", file.getName(), file);
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("getPostObjectFormData")
    void getPostObjectFormData() {
        EndpointEnum endpointEnum = EndpointEnum.OSS_CN_GUANGZHOU;
        String bucketName = "wxhntmy";
        String endpoint = "https://" + bucketName + "." + endpointEnum.getExternalEndpoint();

        File file = new File("D:\\Downloads\\image.png");
        String key = file.getName();

        Map<String, String> formData = AliyunOssUtil.getPostObjectFormData(key, file);
        log.info("formData: {}", JSON.toJSONString(formData, JSONWriter.Feature.WriteMapNullValue));

        MultipartBody.Builder multipartBuilder = new MultipartBody.Builder();
        multipartBuilder.setType(MultipartBody.FORM);
        for (Map.Entry<String, String> entry : formData.entrySet()) {
            multipartBuilder.addFormDataPart(entry.getKey(), entry.getValue());
        }
        multipartBuilder.addFormDataPart("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)");
        multipartBuilder.addFormDataPart("Content-Type", "multipart/form-data");

        String contentType = new MimetypesFileTypeMap().getContentType(file);
        if (contentType == null || contentType.isEmpty()) {
            contentType = "application/octet-stream";
        }
        // "file" 必须最后添加
        multipartBuilder.addFormDataPart(
                "file", file.getName(), RequestBody.create(file, MediaType.parse(contentType)));

        Request request = new Request.Builder()
                        .url(endpoint)
                        .post(multipartBuilder.build())
                        .build();
        OkHttpClient httpClient = new OkHttpClient().newBuilder().build();
        try (Response response = httpClient.newCall(request).execute()) {
            if (response.body() != null) {
                log.info("response: {}", new String(response.body().bytes(), StandardCharsets.UTF_8));
            }
            if (response.isSuccessful()) {
                log.info(file.getName() + " 使用 POST 成功上传！");
            } else {
                log.info("上传失败 " + file.getName());
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("breakpointContinuationUpload")
    void breakpointContinuationUpload() {
        File file = new File("D:\\Downloads\\ideaIU-2023.3.6.exe");
        String key = file.getName();
        AliyunOssUtil.breakpointContinuationUpload("wxhntmy", key, file);
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("putObjectWithProgressListener")
    void putObjectWithProgressListener() {
        File file = new File("D:\\Downloads\\ideaIU-2023.3.6.exe");
        String key = file.getName();
        AliyunOssUtil.putObjectWithProgressListener("wxhntmy", key, file);
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("multipartUploadFile")
    void multipartUploadFile() {
        File file = new File("D:\\Downloads\\ideaIU-2023.3.6.exe");
        String key = file.getName();
        AliyunOssUtil.multipartUploadFile("wxhntmy", key, file);
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("listMultipartUploadFileParts")
    void listMultipartUploadFileParts() {
        JSONArray jsonArray = AliyunOssUtil.listMultipartUploadFileParts("wxhntmy",
                "ideaIU-2023.3.6.exe", "38E8212748864B328C676ABADE98B51E");
        log.info("jsonArray: {}", JSON.toJSONString(jsonArray, JSONWriter.Feature.WriteMapNullValue));
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("getObject")
    void getObject() {

        AliyunOssUtil.getObject("wxhntmy", "image.png", "D:\\Downloads\\image.png", "");
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("readfile")
    void readfile() {
        String filePath = "D:\\Downloads\\1100145028.json";
        byte[] bytes = ReadFile.readFileByFileInputStream(filePath);
        if (bytes != null) {
            String content = new String(bytes, StandardCharsets.UTF_8);
            log.info("contentLength: {}", new File(filePath).length());
            log.info("bytes: {}", JSONObject.parseObject(content).toJSONString(JSONWriter.Feature.WriteMapNullValue));
        }
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("putObjectByObjectMetadata")
    void putObjectByObjectMetadata() {
        String filePath = "D:\\Downloads\\1100145028.json";
        AliyunOssUtil.putObjectByObjectMetadata("wxhntmy", "1100145028.json", new File(filePath), new HashMap<>());
    }
    @Test
    @Tag("AliyunOSS")
    @DisplayName("getObjectMetadata")
    void getObjectMetadata() {
        ObjectMetadata objectMetadata = AliyunOssUtil.getObjectMetadata("wxhntmy", "1100145028.json");
        if (objectMetadata != null) {
            log.info("jsonObject: {}", objectMetadata.getContentDisposition());
        }
    }
    @Test
    @Tag("AliyunOSS")
    @DisplayName("listObjects")
    void listObjects() {
        List<OSSObjectSummary> ossObjectSummaries = AliyunOssUtil.listObjects("wxhntmy", "");
        if (ossObjectSummaries != null) {
            ossObjectSummaries.forEach(ossObjectSummary -> {
                log.info("key: {}", ossObjectSummary.getKey());
            });
        }
    }
    @Test
    @Tag("AliyunOSS")
    @DisplayName("listObjectsV2")
    void listObjectsV2() {
        List<OSSObjectSummary> ossObjectSummaries = AliyunOssUtil.listObjectsV2("wxhntmy", "");
        if (ossObjectSummaries != null) {
            ossObjectSummaries.forEach(ossObjectSummary -> {
                log.info("key: {}", ossObjectSummary.getKey());
            });
        }
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("listAllObjectsByPage")
    void listAllObjectsByPage() {
        List<OSSObjectSummary> ossObjectSummaries =
                AliyunOssUtil.listAllObjectsByPage("wxhntmy", "", 1);
        ossObjectSummaries.forEach(ossObjectSummary -> {
            log.info("key: {}", ossObjectSummary.getKey());
        });
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("listAllObjectsV2ByPage")
    void listAllObjectsV2ByPage() {
        List<OSSObjectSummary> ossObjectSummaries =
                AliyunOssUtil.listAllObjectsV2ByPage("wxhntmy", "", 1);
        ossObjectSummaries.forEach(ossObjectSummary -> {
            log.info("key: {}", ossObjectSummary.getKey());
        });
    }
    @Test
    @Tag("AliyunOSS")
    @DisplayName("selectCsvObject")
    void deleteObject() {
        String sql = "select * from ossobject where code=100121";
        String result = AliyunOssUtil.selectCsvObject("wxhntmy", "组织测试保存表单数据.csv", sql);
        log.info("result: {}", result);
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("selectJsonObject")
    void selectJsonObject() {
        String sql = "select * from ossobject";
        String result = AliyunOssUtil.selectJsonObject("wxhntmy", "1100145028.json", sql);
        log.info("result: {}", result);
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("deleteObjectListByVersion")
    void deleteObjectListByVersion() {
        List<Map<String, String>> versions = new ArrayList<>();
        versions.add(new HashMap<String, String>() {{
            put("key", "1100145028.json");
            put("versionId", "456");
        }});
        versions.add(new HashMap<String, String>() {{
            put("key", "1100145028.json");
            put("versionId", "123");
        }});
        AliyunOssUtil.deleteObjectListByVersion("wxhntmy", versions);
    }

    @Test
    @Tag("AliyunOSS")
    @DisplayName("getObjectPresignedUrl")
    void getObjectPresignedUrl() {
        String url = AliyunOssUtil.getObjectPresignedUrl("wxhntmy", "1711893101642.jpg", 60, TimeUnit.MINUTES);
        log.info("url: {}", url);
    }
}
